#pragma once

#include "cdid3dwindow.h"
#include "CdiRenderObjectList.h"
#include "cdimovementcamera.h"
#include "cdiLightingBase.h"
#include "cdibinarytree.h"

class CdiEngine :
  public CdiD3DWindow
{
private:
  // Private Memebers
  ///////////////////////////

  // Enable rendering Variable
  BOOL m_enableRendering;

  // Background color to render
  D3DCOLOR m_color;

  // Object of all the items to be rendered
  ///////////////////////////
  CdiRenderObjectList* m_gameObjects;

  // As List of Lighting Objects
  CdiRenderObjectList* m_lightingObjects;

  // Create a quick list
  CdiBinaryTree<int,CdiRenderBase*> m_binaryList;

  // Private Methods
  ///////////////////////////
  void Setup();

protected:
  // Camera Object
  CdiMovementCamera*  m_camera;

  // Setup the camera
  ///////////////////////////
  virtual void SetupCamera(D3DXVECTOR3& Position, D3DXVECTOR3& LookAt, D3DXVECTOR3& Up);

  // Updates the camera by centering the mouse in the middle and passes the middle information to the Camera
  void UpdateMouse(void);

  // Render
  virtual void Render();

  // Override to make the work
  virtual void DoWork();

public:
  // Constructors
  ///////////////////////////
  CdiEngine( WNDPROC wndProc );

  CdiEngine( WNDPROC wndProc, bool FullScreen, int width, int height );

  ~CdiEngine();

public:
  // The Game Loop
  void GameLoop();
    
  // Public Object Methods
  ///////////////////////////

  // Add an object to be rendered
  void AddObject( CdiRenderBase* renderObject );

  // Remove an object to be rendered  
  void RemoveObject( int itemIndex ) { throw -1; }

  // Remove and object to be rendered
  void RemoveObject( CdiRenderBase* object ) { throw -1; }

  // Handle the input to the camera
  virtual void HandleInput( UINT Msg, WPARAM wParam, LPARAM lParam );

  // Rendering State; Enable or disabled
  inline void SetRenderingState( BOOL Render ) { m_enableRendering = Render; }
  inline BOOL GetRenderingState() const { return m_enableRendering; }

  // Get the Camera
  CdiCamera* GetCamera();

  // Get the Background color
  inline void SetBackgroundColor( DWORD Color ) { m_color = Color; }
  inline DWORD GetBackgroundColor() const { return m_color; }
  
  // Add lighing Objects
  void AddLight(CdiRenderBase* Light);
  
  // Get a light
  D3DLIGHT9* GetLight(int lightIndex);
};